package com.example.shkjdemo.bluetooth

import android.annotation.SuppressLint
import android.bluetooth.*
import android.bluetooth.BluetoothProfile.A2DP
import android.content.DialogInterface
import android.content.Intent
import android.content.IntentFilter
import android.os.Bundle
import android.os.CountDownTimer
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.example.shkjdemo.R
import com.example.shkjdemo.adapter.MyBluetoothAdapter
import com.example.shkjdemo.bean.BluetoothBean
import com.example.shkjdemo.databinding.ActivityMyBluetoothBinding
import com.orhanobut.logger.Logger
import java.io.InputStream
import java.io.OutputStream
import java.lang.reflect.InvocationTargetException
import java.lang.reflect.Method
import java.util.*
import kotlin.concurrent.thread


class MyBluetoothActivity : AppCompatActivity(), MyBleBroadcastReceiver.ObserverBluetooth,
    SwipeRefreshLayout.OnRefreshListener {
    private lateinit var adapter: MyBluetoothAdapter
    private lateinit var bluetoothViewModel: BluetoothViewModel
    private lateinit var binding: ActivityMyBluetoothBinding
    private var mBluetoothAdapter: BluetoothAdapter? = null
    private val mList: MutableList<BluetoothBean> = arrayListOf()
    private val REQUEST_ENBLE_BT = 0x01
    private lateinit var mLifecycle: MutableLiveData<Boolean>
    private lateinit var mReceiver: MyBleBroadcastReceiver
    private var mBluetoothServerSocket: BluetoothServerSocket? = null
    private var mBluetoothSocket: BluetoothSocket? = null
    private var mBluetoothA2dp: BluetoothA2dp? = null
    private var mDevice: BluetoothDevice? = null
    private var mAlertDialog: AlertDialog? = null
    private var mPosition: Int = 0
    private lateinit var mUUID: UUID
    private var mCountDownTimer: CountDownTimer? = null


    private val TAG = "MyBluetoothActivity"
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        getUUID()
        binding = DataBindingUtil.setContentView(this, R.layout.activity_my_bluetooth)
        bluetoothViewModel = ViewModelProviders.of(this).get(BluetoothViewModel::class.java)
        adapter = MyBluetoothAdapter(R.layout.item_bluetooth)
        binding.rvList.layoutManager = LinearLayoutManager(this)
        binding.rvList.adapter = adapter
        mLifecycle = bluetoothViewModel.isShow
        checkBluetoothState()
        registerReceiver()
        Logger.v(android.os.Build.MODEL)
        initListener()
    }

    private fun initListener() {
        binding.srlPull.setOnRefreshListener(this)
        bluetoothViewModel.isShow.observe(this, androidx.lifecycle.Observer {
            Logger.i("isRefreshing>>> it = $it")
            binding.srlPull.isRefreshing = it
        })

        binding.stopSearch.setOnClickListener {
            //            停止蓝牙搜索
            cancelDiscovery()
        }
        binding.tvSearch.setOnClickListener {
            mList.clear()
//            重新搜索蓝牙设备
//            startDiscovery()
        }

        adapter.setOnItemClickListener { adapter, view, position ->
            mPosition = position
            mDevice = mList[position].device
            showDialog(true, "连接蓝牙")
        }
        adapter.setOnItemLongClickListener { adapter, view, position ->
            showDialog(false, "断开蓝牙连接")
            true
        }
    }

    private fun registerReceiver() {
        mReceiver = MyBleBroadcastReceiver()
        mReceiver.registerObserver(this)
        val filter = IntentFilter(BluetoothDevice.ACTION_FOUND)
        filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED)
        filter.addAction(BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED)
        filter.addAction(BluetoothDevice.ACTION_FOUND)
        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED)
        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED)
        filter.addAction(BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT)
        filter.addCategory(BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY + "." + BluetoothAssignedNumbers.GOOGLE)
        registerReceiver(mReceiver, filter)
    }

    /**
     * @param value true = 连接蓝牙
     * false = 断开连接
     * */
    private fun showDialog(value: Boolean, title: String) {
        val builder = AlertDialog.Builder(this)
        builder.setCancelable(true)
            .setTitle(title)
            .setMessage("")
            .setPositiveButton(getString(R.string.app_sure),
                object : DialogInterface.OnClickListener {
                    override fun onClick(dialog: DialogInterface?, which: Int) {
                        dismissDialog()
                        if (value) {
                            mBluetoothSocket = mDevice?.createRfcommSocketToServiceRecord(mUUID)
//                            connectService()
//                            connectClient()
//            取消扫描
                            cancelDiscovery()
                            createBond()
                        } else {
                            disconnect()
                        }

                    }
                })
            .setNegativeButton(
                getString(R.string.app_cancel)
            ) { _, _ -> dismissDialog() }
            .setNeutralButton("查看详情") { _, _ ->
                {
                    dismissDialog()
                }
            }
        mAlertDialog = builder.create()
        mAlertDialog?.show()
    }

    private fun dismissDialog() {
        if (mAlertDialog != null) {
            mAlertDialog!!.dismiss()
        }
    }

    /**
     * 连接成为服务端
     * */
    private fun connectService() {
        mBluetoothServerSocket =
            mBluetoothAdapter?.listenUsingRfcommWithServiceRecord(
                "com.example.shkjdemo",
                mUUID
            )
        try {
            val connectThread = ConnectThread(mBluetoothSocket!!, mDevice!!)
            connectThread.start()
        } catch (e: Exception) {
            Logger.e("$TAG,e = ${e.message}")
        }
    }

    private class ConnectThread(socket: BluetoothSocket, device: BluetoothDevice) :
        Thread() {
        private val TAG = "ConnectThread"
        private var mSocket: BluetoothSocket = socket
        private var mDevice: BluetoothDevice = device
        var inputStream: InputStream? = null
        var outputStream: OutputStream? = null


        override fun run() {
            super.run()
            mSocket = mDevice.javaClass.getMethod(
                "createRfcommSocket", *arrayOf<Class<*>?>(
                    Int::class.javaPrimitiveType
                )
            ).invoke(mDevice, 1) as BluetoothSocket

            thread {
                try {
                    mSocket.connect()
                    Logger.e("$TAG,socket 连接成功")
                } catch (e: Exception) {
                    Logger.e("$TAG,socket 连接失败${e.message}")
                } finally {
                    inputStream = mSocket.inputStream
                    outputStream = mSocket.outputStream
                }
            }
        }
    }

    /**
     * 连接为客户端
     * */
    private fun connectClient() {
        thread {
            //
            cancelDiscovery()
            try {
                mBluetoothSocket?.connect()
                Logger.e("${TAG},connectClient 连接成功")
            } catch (e: Exception) {
                try {
                    mBluetoothSocket?.close()
                } catch (e: Exception) {
                    Logger.e(TAG, e.message)
                    return@thread
                } finally {
                    Logger.e("$TAG, ${e.message}")
                }
            } finally {

            }
        }
    }

    /**
     * 检查蓝牙状态
     * */
    private fun checkBluetoothState() {
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
        if (mBluetoothAdapter == null) {
            // 说明此设备不支持蓝牙操作
            Toast.makeText(this, "此设备不支持蓝牙操作", Toast.LENGTH_LONG).show()
            return
        }
        // 没有开始蓝牙,启动蓝牙
        if (!mBluetoothAdapter?.isEnabled!!) {
            val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
            startActivityForResult(enableBtIntent, REQUEST_ENBLE_BT)
        }
        initBluetoothSet()
//        启动发现设备
        val isStart = startDiscovery()
//绑定BluetoothA2DP，获得service
        getBluetoothA2DP()
        Logger.i("$TAG,checkBluetoothState>>> isStart = $isStart")
    }

    /**
     * 开始操作蓝牙相关信息
     * */
    private fun initBluetoothSet() {
        Log.v("mLifecycle", mLifecycle.value.toString())
        Log.v("mLifecycle2", bluetoothViewModel.isShow.value.toString())

//获取已配对设备
        val pairedDevices: Set<BluetoothDevice> = mBluetoothAdapter!!.bondedDevices
        if (pairedDevices.isNotEmpty()) {
            pairedDevices.forEach {
                mList.add(
                    BluetoothBean(
                        "(已配对) ${it.name}",
                        "address ${it.address}"
                                + "\nbondState ${it.bondState}"
                                + "\ntype ${it.type}"
                                + "\nuuids ${it.uuids}",
                        it
                    )
                )
            }
        }
        adapter.setNewData(mList)
        adapter.notifyDataSetChanged()
    }

    private fun startCountTimer() {
        if (mCountDownTimer == null) {
            mCountDownTimer = object : CountDownTimer(10000L, 1000) {
                override fun onFinish() {
                    binding.srlPull.isRefreshing = false
                }

                override fun onTick(millisUntilFinished: Long) {

                }

            }.start()
        } else {
            mCountDownTimer?.start()
        }
    }

    private fun cancelCountTimer() {
        mCountDownTimer?.cancel()
    }


    override fun onActivityResult(
        requestCode: Int,
        resultCode: Int,
        data: Intent?
    ) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == REQUEST_ENBLE_BT) {
//
            if (mBluetoothAdapter?.isEnabled!!) {
                initBluetoothSet()
            } else {
                Toast.makeText(this, "蓝牙没有打开", Toast.LENGTH_LONG).show()
            }
        }
    }

    override fun addDevice(device: BluetoothDevice) {
        if (device.name == null) {
            return
        }
        if (device.bluetoothClass.deviceClass == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET
            || device.bluetoothClass.deviceClass == BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE
        ) {
//            扫描结果只保留蓝牙耳机
            adapter.addData(
                BluetoothBean(
                    "蓝牙名称 ${device.name}",
                    "address ${device.address}"
                            + "\nbondState ${device.bondState}"
                            + "\ntype ${device.type}"
                            + "\nuuids ${device.uuids}",
                    device
                )
            )
        }
    }

    override fun connect(device: BluetoothDevice) {
        connect()
    }

    private fun getBluetoothA2DP() {
        if (mBluetoothAdapter == null) {
            return
        }
        if (mBluetoothA2dp != null) {
            return
        }
//绑定a2dp 代理
        mBluetoothAdapter!!.getProfileProxy(
            this,
            object : BluetoothProfile.ServiceListener {
                override fun onServiceConnected(profile: Int, proxy: BluetoothProfile) {
                    if (profile == A2DP) { //Service连接成功，获得BluetoothA2DP
                        mBluetoothA2dp = proxy as BluetoothA2dp
                    }
                }

                override fun onServiceDisconnected(profile: Int) {
//                    断开连接

                }
            },
            A2DP
        )
    }

    private fun createBond() {
        Log.i(TAG, "createBond")
        mDevice?.createBond()
    }

    //connect和disconnect都是hide方法，普通应用只能通过反射机制来调用该方法
    @SuppressLint("DiscouragedPrivateApi")
    private fun connect() {
        Log.i(TAG, "connect")
        if (mBluetoothA2dp == null) {
            return
        }
        if (mDevice == null) {
            return
        }

        try {
            val connect: Method =
                mBluetoothA2dp?.javaClass!!.getDeclaredMethod(
                    "connect",
                    BluetoothDevice::class.java
                )
            connect.isAccessible = true
            connect.invoke(mBluetoothA2dp, mDevice)
        } catch (e: NoSuchMethodException) {
            Log.e(TAG, "connect exception:$e")
            e.printStackTrace()
        } catch (e: InvocationTargetException) {
            Log.e(TAG, "connect exception:$e")
            e.printStackTrace()
        } catch (e: IllegalAccessException) {
            Log.e(TAG, "connect exception:$e")
            e.printStackTrace()
        }
    }

    @SuppressLint("DiscouragedPrivateApi")
    /**  断开连接*/
    private fun disconnect() {
        Log.i(TAG, "disconnect")
        if (mBluetoothA2dp == null) {
            return
        }
        if (mDevice == null) {
            return
        }

        try {
            val disconnect = mBluetoothA2dp?.javaClass?.getDeclaredMethod(
                "disconnect",
                BluetoothDevice::class.java
            )
            disconnect?.isAccessible = true
            disconnect?.invoke(mBluetoothA2dp, mDevice)
        } catch (e: NoSuchMethodException) {
            Log.e(TAG, "connect exception:$e")
            e.printStackTrace();
        } catch (e: InvocationTargetException) {
            Log.e(TAG, "connect exception:$e")
            e.printStackTrace();
        } catch (e: IllegalAccessException) {
            Log.e(TAG, "connect exception:$e")
            e.printStackTrace();
        }
    }

    //注意，在程序退出之前（OnDestroy），需要断开蓝牙相关的Service
    //否则，程序会报异常：service leaks
    override fun onDestroy() {
        super.onDestroy()
        cancelCountTimer()
        cancelDiscovery()
        //关闭ProfileProxy，也就是断开service连接
        mBluetoothAdapter?.closeProfileProxy(BluetoothProfile.A2DP, mBluetoothA2dp);
        /* if (mBluetoothAdapter?.isEnabled!!) {
 //        关闭蓝牙
             val ret = mBluetoothAdapter?.disable()
             Log.i(TAG, "disable adapter:$ret")
         }*/
    }

    /**
     * 打开搜索蓝牙设备
     * */
    private fun startDiscovery(): Boolean? {
        return mBluetoothAdapter?.startDiscovery()
    }

    /**
     * 取消寻找设备
     *
     * 注意 执行 discovery 对于蓝牙适配器来说是一个非常繁重的过程，并且会消耗大量资源。在找到要连接的设备后，
     * 要确保使用 cancelDiscovery() 来停止发现，然后尝试连接。如果您已经和某台设备进行连接，
     * 那么这个时候执行发现操作会大幅度的减少此连接可用的带宽！因此不应该在处于连接状态的时候执行发现操作！
     * */
    private fun cancelDiscovery() {
//        取消寻找设备
        mBluetoothAdapter?.cancelDiscovery()
    }

    private fun getUUID(): UUID {
        mUUID = UUID.fromString("00001105-0000-1000-8000-00805f9B34FB")
        Logger.i("$TAG,getUUID = $mUUID")
        return mUUID
    }

    override fun onRefresh() {
        Logger.v("$TAG,onRefresh...")
        if (binding.srlPull.isRefreshing) {
            startCountTimer()
//            重新搜索蓝牙设备
            startDiscovery()
        }
    }
}
